package org.budo.mybatis.dao.impl;

import javax.sql.DataSource;

import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.budo.mybatis.dao.entity.configer.MyBatisDaoEntityConfiger;
import org.budo.mybatis.dao.entity.configer.impl.AnnotationEntityConfiger;
import org.budo.mybatis.dao.statement.builder.StatementBuilder;
import org.budo.mybatis.dao.statement.builder.impl.DefaultStatementBuilder;
import org.budo.mybatis.executor.keygen.BudoJdbc3KeyGenerator;
import org.budo.support.assertion.Assert;
import org.mybatis.spring.SqlSessionFactoryBean;

import lombok.Getter;
import lombok.Setter;

/**
 * @author limingwei
 * @date 2016年6月4日 下午4:37:57
 */
@Getter
@Setter
public abstract class AbstractMybatisDao {
    private SqlSessionFactory sqlSessionFactory;

    private SqlSession sqlSession;

    private Configuration configuration;

    private DataSource dataSource;

    private StatementBuilder statementBuilder;

    private MyBatisDaoEntityConfiger entityConfiger = new AnnotationEntityConfiger();

    private KeyGenerator keyGenerator = new BudoJdbc3KeyGenerator();

    public StatementBuilder getStatementBuilder() {
        if (null == this.statementBuilder) {
            synchronized (AbstractMybatisDao.class) {
                if (null == this.statementBuilder) {
                    DefaultStatementBuilder budoMyBatisDaoStatementBuilder = new DefaultStatementBuilder();
                    budoMyBatisDaoStatementBuilder.setEntityConfiger(this.getEntityConfiger());
                    this.statementBuilder = budoMyBatisDaoStatementBuilder;
                }
            }
        }
        return this.statementBuilder;
    }

    public SqlSessionFactory getSqlSessionFactory() {
        if (null == this.sqlSessionFactory && null != this.dataSource) {
            this.sqlSessionFactory = this.initSqlSessionFactory(this.dataSource);
        }
        return this.sqlSessionFactory;
    }

    private SqlSessionFactory initSqlSessionFactory(DataSource dataSource) {
        try {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource);
            sqlSessionFactoryBean.afterPropertiesSet();
            return sqlSessionFactoryBean.getObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Configuration getConfiguration() {
        if (null == this.configuration && null != this.getSqlSessionFactory()) {
            this.configuration = this.getSqlSessionFactory().getConfiguration();
        }

        Assert.notNull(this.configuration, "this.configuration is null");
        return this.configuration;
    }

    public DataSource getDataSource() {
        if (null == this.dataSource && null != this.getConfiguration()) {
            this.dataSource = this.getConfiguration().getEnvironment().getDataSource();
        }
        return this.dataSource;
    }
}